/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework.autoproxy;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable;

/**
 * Auto-proxy creator that considers infrastructure Advisor beans only,
 * ignoring any application-defined Advisors.
 *
 * @author Juergen Hoeller
 * @since 2.0.7
 */
@SuppressWarnings("serial")
/**
 * 【重要】InfrastructureAdvisorAutoProxyCreator 间接实现了BeanPostProcessor接口, 用于完成bean的aop操作,
 * 类似于 @EnableAspectJAutoProxy是向容器中注入的bean --> AnnotationAwareAspectJAutoProxyCreator,
 * InfrastructureAdvisorAutoProxyCreator和 AnnotationAwareAspectJAutoProxyCreator 都继承了
 * AbstractAutoProxyCreator, 用于完成aop的处理
 * InfrastructureAdvisorAutoProxyCreator 实现了BeanPostProcessor接口, 由前期ioc和aop学习, 我们知道bean的创建过程中先后
 * 使用8次BeanPostProcessor, 下面, 解析 InfrastructureAdvisorAutoProxyCreator 在八次使用中的作用:
 *
 * *第一次: 使用的是InstantiationAwareBeanPostProcessor, 判断是否直接生成代理对象, InfrastructureAdvisorAutoProxyCreator
 * 继承了 AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor接口,
 * 调用了其 postProcessBeforeInstantiation(Class<?>, String)方法
 * 【总结】这里不会生成代理对象, 走正常的bean的创建流程
 *
 * 第二次: 使用的是SmartInstantiationAwareBeanPostProcessor, 用于推断实例化bean时所采用的构造器,
 * InstantiationAwareBeanPostProcessor 继承了 AbstractAutoProxyCreator 类实现了 SmartInstantiationAwareBeanPostProcessor 接口,
 * 调用了其 determineCandidateConstructors(Class<?>, String)方法, 该方法返回null, 其不参与构造器推断
 * 【总结】 这里不参与构造器的推断
 *
 * 第三次: 使用的是MergedBeanDefinitionPostProcessor, 用于提前找到属性注入点, InstantiationAwareBeanPostProcessor
 * 没有直接或间接实现MergedBeanDefinitionPostProcessor接口, 所以这里跳过
 * 【总结】这里不会使用到当前bpp
 *
 * 第四次: 使用的是SmartInstantiationAwareBeanPostProcessor, 用于：如果在支持循环依赖的前提下, 会将实例化的bean对象,
 * 创建对应的三级缓存对象singletonFactory对象, 该对象的方法getEarlyBeanReference方法中第四次使用了BeanPostProcessor,
 * 用于提前暴露实例化但未初始化的bean
 * 【总结】 如果存在循环引用, 会提前调用 wrapIfNecessary 方法进行aop, 创建代理对象并返回
 *
 * 第五次：使用的是InstantiationAwareBeanPostProcessor, 用于判断bean是否需要属性注入, InfrastructureAdvisorAutoProxyCreator
 * 继承了 AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor 接口, 调用了其
 * postProcessAfterInstantiation(Object, String)方法, 该方法返回true, 表示不会阻断属性注入
 * 【总结】不会影响属性注入
 *
 * 第六次: 使用的是InstantiationAwareBeanPostProcessor, 用于bean的属性注入, InfrastructureAdvisorAutoProxyCreator  继承了
 * AbstractAutoProxyCreator 类实现了 InstantiationAwareBeanPostProcessor 接口, 调用了其
 * postProcessProperties(PropertyValues, Object, String)方法，该方法没有作任何处理
 * 【总结】不会参与属性注入
 *
 * 第七次: 使用的是BeanPostProcessor, 在bean属性注入之后, 执行初始化方法之前, 对bean进行aop操作,
 * InfrastructureAdvisorAutoProxyCreator  继承了 AbstractAutoProxyCreator 类实现了 BeanPostProcessor 接口,
 * 调用了其 postProcessBeforeInitialization(Object, String)方法，该方法没有作任何处理
 * 【总结】不会参与
 *
 * 第八次: 使用的是BeanPostProcessor, 在执行初始化方法之后, 对bean进行aop操作, InfrastructureAdvisorAutoProxyCreator 继承了
 * AbstractAutoProxyCreator 类实现了 BeanPostProcessor 接口, 调用了其 postProcessBeforeInitialization(Object, String)方法,
 * 生成代理对象
 * 【总结】这里是核心, 创建aop后的代理对象
 *
 *
 */
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	@Nullable
	private ConfigurableListableBeanFactory beanFactory;


	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		this.beanFactory = beanFactory;
	}

	@Override
	protected boolean isEligibleAdvisorBean(String beanName) {
		return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
				this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
	}

}
